using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using XDebugConsole;
using XNgine.ConsoleComponent.Exceptions;
using XNgine.DebugConsole.Commands;
using XNgine.Services;

namespace XNgine.DebugConsole
{
    public class Console : XDebugConsole.DebugConsole, IConsole
    {
        public bool ThrowExceptions { get; set; }

        private readonly List<CommandResult> _CommandHistory = new List<CommandResult>();
        public List<CommandResult> CommandHistory
        {
            get { return _CommandHistory; }
        }

        public Console() : base(new GameInfo()) { }

        public CommandResult Execute(Command command, params object[] args)
        {
            CommandResult result;
            try
            {
                result = command.Execute(args);
            }
            catch (ConsoleException e)
            {
                result = HandleException(e);
            }
            CommandHistory.Add(result);
            return result;
        }

        public CommandResult Interpret(string commandString)
        {
            CommandResult result;
            try
            {
                result = CommandInterpreter.Interpret(commandString);
            }
            catch (ConsoleException e)
            {
                result = HandleException(e);
            }
            CommandHistory.Add(result);
            return result;
        }

        private CommandResult HandleException(ConsoleException e)
        {
            if (e == null) throw new ArgumentNullException("e");
            if (ThrowExceptions)
            {
                throw e;
            }
            else
            {
                return new CommandResult
                {
                    ReturnObject = e,
                    Output = string.Format("Exception: {0}", e.Message)
                };
            }
        }

        private class GameInfo : IContainGameInfo
        {
            private static ICameraManagement CameraManagement
            {
                get
                {
                    return XEngine.Instance.GetService<ICameraManagement>();
                }
            }

            public Game Game
            {
                get { return XEngine.Instance; }
            }

            public Matrix WorldMatrix
            {
                get { return Matrix.Identity; }
            }

            public Matrix ViewMatrix
            {
                get { return CameraManagement.ActiveCamera.View; }
            }

            public Matrix ProjectionMatrix
            {
                get { return CameraManagement.ActiveCamera.Projection; }
            }
        }
    }
}